package org.liveboardgames.agricola.domain.farm;

import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.liveboardgames.agricola.domain.common.IResourceContainer;
import org.liveboardgames.agricola.domain.common.Peep;
import org.liveboardgames.agricola.model.structure.Visitable;
import org.liveboardgames.agricola.model.structure.Visitor;

public class FarmTile implements Serializable, Visitable, IResourceContainer {

  /** The unique identifier of the tile, application-wide. */
  private Long uniqueId;

  /** The ID of the tile in the farm */
  private Long id;

  private Set<Peep> peeps;

  private Pasture pasture;

  private String farmElement;

  private Farm farm;

  private Map<String, Integer> resources;

  /**
   * @param uniqueId
   *          the {@link #uniqueId} to set
   */
  public void setUniqueId(Long uniqueId) {
    this.uniqueId = uniqueId;
  }

  /**
   * @return the {@link #uniqueId}
   */
  public Long getUniqueId() {
    return uniqueId;
  }

  /**
   * @return the {@link #id}
   */
  public Long getId() {
    return id;
  }

  /**
   * @param id
   *          the {@link #id} to set
   */
  public void setId(Long id) {
    this.id = id;
  }

  /**
   * @return the {@link #peeps}
   */
  public Set<Peep> getPeeps() {
    return peeps;
  }

  /**
   * @param peeps
   *          the {@link #peeps} to set
   */
  public void setPeeps(Set<Peep> peeps) {
    this.peeps = peeps;
  }

  public void addPeep(Peep peep) {
    if (this.peeps == null) {
      this.peeps = new HashSet<Peep>();
    }
    this.peeps.add(peep);
  }

  /**
   * @return the {@link #pasture}
   */
  public Pasture getPasture() {
    return pasture;
  }

  /**
   * @param pasture
   *          the {@link #pasture} to set
   */
  public void setPasture(Pasture pasture) {
    this.pasture = pasture;
  }

  /**
   * @return the {@link #farmElement}
   */
  public String getFarmElement() {
    return farmElement;
  }

  /**
   * @param farmElement
   *          the {@link #farmElement} to set
   */
  public void setFarmElement(String farmElement) {
    this.farmElement = farmElement;
  }

  /**
   * @return the {@link #farm}
   */
  public Farm getFarm() {
    return farm;
  }

  /**
   * @param farm
   *          the {@link #farm} to set
   */
  public void setFarm(Farm farm) {
    this.farm = farm;
  }

  /**
   * @return the {@link #resources}
   */
  public Map<String, Integer> getResources() {
    return resources;
  }

  /**
   * @param resources
   *          the {@link #resources} to set
   */
  public void setResources(Map<String, Integer> resources) {
    this.resources = resources;
  }

  public void addResource(String type, Integer quantity) {
    if (this.resources == null) {
      this.resources = new HashMap<String, Integer>();
    }
    Integer currentQuantity = this.resources.get(type);
    if (currentQuantity == null) {
      currentQuantity = new Integer(0);
    }
    this.resources.put(type, Math.max(0, currentQuantity + quantity));
  }

  public void addResources(Map<String, Integer> resources) {
    if (resources != null) {
      for (String type : resources.keySet()) {
        addResource(type, resources.get(type));
      }
    }
  }
  
  public boolean isFree() {
    return this.farmElement == null || this.pasture == null;
  }

  public void acceptVisit(Visitor visitor) {
    visitor.visit(this);
  }

  @Override
  public boolean equals(Object obj) {
    boolean isEqual = false;
    if (obj != null && obj instanceof FarmTile) {
      isEqual = ((FarmTile)obj).id != null && ((FarmTile)obj).id.equals(this.id);
    }
    return isEqual;
  }

  @Override
  public int hashCode() {
    return id.intValue();
  }

}
